import { Component } from 'react'
import Taro from '@tarojs/taro'
import { View, Textarea, Button, Canvas, Image } from '@tarojs/components'
import { createSelectorQuery } from '@tarojs/taro'
import './index.scss'

// 仍然使用markdown-it
import MarkdownIt from 'markdown-it'
const md = new MarkdownIt()

export default class Index extends Component {
  constructor(props) {
    super(props)
    this.state = {
      markdown: '',
      canvasId: 'markdown-canvas',
      imageUrl: '',
      canvasWidth: 300,
      canvasHeight: 500,
      isPreviewMode: false,
      debugInfo: [],
      showDebug: false
    }
  }

  // 处理Markdown输入变化
  handleInputChange = (e) => {
    this.setState({
      markdown: e.detail.value
    })
  }

  // 添加记录调试信息的方法
  logDebug = (message) => {
    const { debugInfo } = this.state;
    const timestamp = new Date().toLocaleTimeString();
    const newDebugInfo = [`${timestamp}: ${message}`, ...debugInfo].slice(0, 20); // 仅保留最近20条

    this.setState({ debugInfo: newDebugInfo });
    console.log(message); // 仍然使用console.log以便在开发工具中查看
  }

  // 转换为图片并切换到预览模式
  convertToImage = () => {
    try {
      this.logDebug('转换函数被调用');

      // 使用微信原生API
      wx.showToast({
        title: '处理中...',
        icon: 'loading',
        mask: true,
        duration: 2000
      });

      // 直接改变状态并生成图片，不使用套嵌的回调
      this.setState({ isPreviewMode: true });

      // 稍微延迟再生成图片，确保UI更新
      setTimeout(() => {
        this.generateImage();
      }, 500);
    } catch (e) {
      this.logDebug('错误: ' + (e.message || '未知错误'));
      Taro.showModal({
        title: '发生错误',
        content: JSON.stringify(e),
        showCancel: false
      });
    }
  }

  // 返回编辑模式
  backToEditor = () => {
    this.setState({
      isPreviewMode: false
    })
  }

  // 生成图片
  generateImage = async () => {
    console.log('开始生成图片'); // 添加调试日志
    try {
      Taro.showLoading({
        title: '生成中...',
        mask: true
      });

      // 获取设备信息
      const systemInfo = Taro.getSystemInfoSync();
      console.log('设备信息:', systemInfo); // 记录设备信息以便调试

      // 根据设备调整像素比
      const pixelRatio = Math.min(systemInfo.pixelRatio || 2, 2); // 限制最大像素比
      const windowWidth = systemInfo.windowWidth;

      // 设置内容宽度
      const contentWidth = windowWidth - 40;

      // 估算高度
      const { markdown } = this.state;
      let estimatedHeight = this.estimateMarkdownHeight(markdown, contentWidth);

      // 确保有足够的空间 - 使用更大的最小高度
      estimatedHeight = Math.max(estimatedHeight, 1500); // 至少1500px高度

      // 设置Canvas尺寸
      const canvasWidth = contentWidth;
      const canvasHeight = estimatedHeight;

      this.setState({
        canvasWidth,
        canvasHeight
      }, async () => {
        // 绘制Canvas
        const canvas = await new Promise(resolve => {
          const q = createSelectorQuery()
          q.select(`#${this.state.canvasId}`).fields({ node: true, size: true }).exec(res => {
            resolve(res[0].node)
          })
        })

        canvas.width = canvasWidth * pixelRatio;
        canvas.height = canvasHeight * pixelRatio;

        const ctx = canvas.getContext('2d');
        ctx.scale(pixelRatio, pixelRatio);
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, canvasWidth, canvasHeight);

        // 渲染Markdown
        this.renderMarkdown(ctx, markdown, 20, 20, contentWidth - 40);

        // 转为图片
        const tempFilePath = await new Promise((resolve, reject) => {
          Taro.canvasToTempFilePath({
            canvas: canvas,
            success: (res) => {
              resolve(res.tempFilePath)
            },
            fail: (err) => {
              reject(err)
            }
          })
        });

        this.setState({
          imageUrl: tempFilePath
        });

        Taro.hideLoading();
        Taro.showToast({
          title: '图片生成成功',
          icon: 'success',
          duration: 1500
        });
      });
    } catch (error) {
      // 输出更详细的错误信息
      console.error('生成图片失败', error, error.stack);
      Taro.hideLoading();
      Taro.showToast({
        title: '生成图片失败: ' + (error.message || '未知错误'),
        icon: 'none',
        duration: 3000
      });
    }
  }

  // 保存图片
  saveImage = () => {
    const { imageUrl } = this.state
    if (!imageUrl) {
      Taro.showToast({
        title: '图片生成中，请稍候',
        icon: 'none'
      })
      return
    }

    Taro.saveImageToPhotosAlbum({
      filePath: imageUrl,
      success: () => {
        Taro.showToast({
          title: '保存成功',
          icon: 'success'
        })
      },
      fail: (err) => {
        console.error('保存失败', err)
        Taro.showToast({
          title: '保存失败',
          icon: 'none'
        })
      }
    })
  }

  // 估算Markdown渲染高度
  estimateMarkdownHeight = (markdown, width) => {
    const baseFontSize = 16
    const headingSizes = {
      h1: 24,
      h2: 22,
      h3: 20,
      h4: 18,
      h5: 16,
      h6: 16
    }
    const lineHeight = 1.5

    // 解析markdown获取tokens
    const tokens = md.parse(markdown, {})

    let totalHeight = 40 // 初始上下边距
    let listLevel = 0
    let inCodeBlock = false

    for (let i = 0; i < tokens.length; i++) {
      const token = tokens[i]

      switch (token.type) {
        case 'heading_open':
          const level = parseInt(token.tag.slice(1))
          i++ // 移动到内容token

          if (tokens[i] && tokens[i].type === 'inline') {
            const text = tokens[i].content
            const fontSize = headingSizes[`h${level}`]

            // 估算标题所需行数
            const lines = this.estimateLines(text, width, fontSize)
            totalHeight += lines * fontSize * lineHeight + 20 // 标题行高加上间距
          }
          break

        case 'paragraph_open':
          i++
          if (tokens[i] && tokens[i].type === 'inline') {
            const text = tokens[i].content

            // 估算段落所需行数
            const lines = this.estimateLines(text, width, baseFontSize)
            totalHeight += lines * baseFontSize * lineHeight + 10 // 段落行高加上间距
          }
          break

        case 'bullet_list_open':
        case 'ordered_list_open':
          listLevel++
          break

        case 'bullet_list_close':
        case 'ordered_list_close':
          listLevel--
          if (listLevel === 0) {
            totalHeight += 10 // 列表结束后添加间距
          }
          break

        case 'list_item_open':
          i++
          // 寻找列表项内容
          while (i < tokens.length && tokens[i].type !== 'list_item_close') {
            if (tokens[i].type === 'paragraph_open') {
              i++
              if (tokens[i] && tokens[i].type === 'inline') {
                const text = tokens[i].content

                // 估算列表项所需行数
                const lines = this.estimateLines(text, width - 20 * listLevel, baseFontSize)
                totalHeight += lines * baseFontSize * lineHeight + 5 // 列表项行高加上间距
              }
            }
            i++
          }
          break

        case 'code_block':
          const code = token.content
          const codeLines = code.split('\n').length
          totalHeight += codeLines * 14 * lineHeight + 20 // 代码行高加上间距
          break

        case 'fence':
          const fenceCode = token.content
          const fenceLines = fenceCode.split('\n').length
          totalHeight += fenceLines * 14 * lineHeight + 20 // 代码行高加上间距
          break

        case 'blockquote_open':
          totalHeight += 10 // 引用开始前间距
          break

        case 'blockquote_close':
          totalHeight += 10 // 引用结束后间距
          break
      }
    }

    // 确保足够的底部空间
    totalHeight += 40

    // 根据内容复杂度动态调整高度
    const contentComplexity = markdown.length / 100; // 粗略估计复杂度
    const scalingFactor = 1 + Math.min(2, contentComplexity / 10); // 上限是3倍

    totalHeight = totalHeight * scalingFactor;

    // 显著增加额外空间，确保内容不会被截断
    totalHeight += 800; // 由之前的200px增加到800px

    return totalHeight
  }

  // 估算文本行数
  estimateLines = (text, maxWidth, fontSize) => {
    // 简单估算：假设每个字符宽度为fontSize的一半
    const charsPerLine = Math.floor(maxWidth / (fontSize * 0.5))

    // 考虑中文和英文混排
    let lineCount = 0
    let currentLineLength = 0

    for (let i = 0; i < text.length; i++) {
      const char = text[i]

      // 中文字符占用更多空间
      const charWidth = /[\u4e00-\u9fa5]/.test(char) ? 1 : 0.5

      currentLineLength += charWidth

      if (currentLineLength >= charsPerLine) {
        lineCount++
        currentLineLength = 0
      }
    }

    // 加上最后一行
    if (currentLineLength > 0) {
      lineCount++
    }

    // 至少返回1行
    return Math.max(1, lineCount)
  }

  // 渲染Markdown到Canvas
  renderMarkdown = (ctx, markdown, x, y, maxWidth) => {
    const baseFontSize = 16
    const headingSizes = {
      h1: 24,
      h2: 22,
      h3: 20,
      h4: 18,
      h5: 16,
      h6: 16
    }
    const lineHeight = 1.5

    // 解析markdown
    const tokens = md.parse(markdown, {})

    let currentY = y
    let listLevel = 0
    let listCounter = 0

    for (let i = 0; i < tokens.length; i++) {
      const token = tokens[i]

      switch (token.type) {
        case 'heading_open':
          const level = parseInt(token.tag.slice(1))
          i++

          if (tokens[i] && tokens[i].type === 'inline') {
            const text = tokens[i].content
            const fontSize = headingSizes[`h${level}`]

            // 增加标题前的间距
            currentY += 20

            // 设置标题样式
            ctx.font = `bold ${fontSize}px sans-serif`
            ctx.fillStyle = '#000000'

            // 绘制标题
            currentY = this.drawWrappedText(ctx, text, x, currentY, maxWidth, fontSize)

            // 标题后的间距
            currentY += 10
          }
          break

        case 'paragraph_open':
          i++
          if (tokens[i] && tokens[i].type === 'inline') {
            const text = tokens[i].content

            // 设置段落样式
            ctx.font = `${baseFontSize}px sans-serif`
            ctx.fillStyle = '#333333'

            // 段落前的间距
            currentY += 10

            // 绘制段落
            currentY = this.drawWrappedText(ctx, text, x, currentY, maxWidth, baseFontSize)

            // 段落后的间距
            currentY += 10
          }
          break

        case 'bullet_list_open':
          listLevel++
          break

        case 'ordered_list_open':
          listLevel++
          listCounter = 1
          break

        case 'bullet_list_close':
        case 'ordered_list_close':
          listLevel--
          if (listLevel === 0) {
            listCounter = 0
            currentY += 10
          }
          break

        case 'list_item_open':
          const isOrdered = tokens[i - 1] && (tokens[i - 1].type === 'ordered_list_open' ||
                           (tokens[i - 2] && tokens[i - 2].type === 'ordered_list_open'));

          // 缩进列表项
          const indent = x + 20 * listLevel

          // 设置列表项样式
          ctx.font = `${baseFontSize}px sans-serif`
          ctx.fillStyle = '#333333'

          // 绘制列表标记
          if (isOrdered) {
            ctx.fillText(`${listCounter}.`, indent - 15, currentY + baseFontSize)
            listCounter++
          } else {
            ctx.beginPath()
            ctx.arc(indent - 10, currentY + baseFontSize / 2, 3, 0, Math.PI * 2)
            ctx.fill()
          }

          // 处理列表项内容
          i++
          while (i < tokens.length && tokens[i].type !== 'list_item_close') {
            if (tokens[i].type === 'paragraph_open') {
              i++
              if (tokens[i] && tokens[i].type === 'inline') {
                const text = tokens[i].content

                // 绘制列表项内容
                currentY = this.drawWrappedText(ctx, text, indent, currentY, maxWidth - indent + x, baseFontSize)
              }
            } else if (tokens[i].type === 'bullet_list_open' || tokens[i].type === 'ordered_list_open') {
              // 嵌套列表前添加一些间距
              currentY += 5
            }
            i++
          }

          // 列表项后的间距
          currentY += 5
          break

        case 'code_block':
        case 'fence':
          const code = token.content

          // 代码块前的间距
          currentY += 10

          // 绘制代码块背景
          const codeLines = (token.type === 'fence' ? token.content : token.content).split('\n')
          const codeHeight = codeLines.length * 14 * lineHeight

          ctx.fillStyle = '#f6f8fa'
          ctx.fillRect(x, currentY, maxWidth, codeHeight + 20)

          // 设置代码样式
          ctx.font = '14px monospace'
          ctx.fillStyle = '#333333'

          // 绘制代码
          currentY += 10 // 代码顶部内边距
          for (const line of codeLines) {
            currentY += 14 * lineHeight
            ctx.fillText(line, x + 10, currentY)
          }

          // 代码块后的间距
          currentY += 10
          break

        case 'blockquote_open':
          // 引用样式
          ctx.fillStyle = '#f0f0f0'
          i++

          let quoteContent = ''
          let quoteHeight = 0

          // 收集引用内容
          while (i < tokens.length && tokens[i].type !== 'blockquote_close') {
            if (tokens[i].type === 'paragraph_open') {
              i++
              if (tokens[i] && tokens[i].type === 'inline') {
                quoteContent += tokens[i].content + '\n'

                // 估算引用高度
                const lines = this.estimateLines(tokens[i].content, maxWidth - 20, baseFontSize)
                quoteHeight += lines * baseFontSize * lineHeight
              }
            }
            i++
          }

          // 绘制引用背景和左侧边框
          ctx.fillStyle = '#f5f5f5'
          ctx.fillRect(x, currentY, maxWidth, quoteHeight + 20)

          ctx.fillStyle = '#dddddd'
          ctx.fillRect(x, currentY, 5, quoteHeight + 20)

          // 设置引用文本样式
          ctx.font = `${baseFontSize}px sans-serif`
          ctx.fillStyle = '#666666'

          // 绘制引用文本
          currentY += 10 // 引用顶部内边距
          currentY = this.drawWrappedText(ctx, quoteContent, x + 15, currentY, maxWidth - 20, baseFontSize)

          // 引用后的间距
          currentY += 10
          break
      }
    }

    return currentY
  }

  // 绘制换行文本
  drawWrappedText = (ctx, text, x, y, maxWidth, fontSize) => {
    // 处理特殊格式
    const parts = this.parseFormattedText(text)

    const lineHeight = fontSize * 1.5
    let currentY = y + fontSize // 开始位置加上字体大小

    let currentLine = ''
    let currentLineWidth = 0
    let currentFormat = 'normal'

    for (const part of parts) {
      const { text: partText, format } = part

      // 拆分文本为词
      const words = this.splitIntoWords(partText)

      for (const word of words) {
        // 应用当前格式
        if (format === 'bold') {
          ctx.font = `bold ${fontSize}px sans-serif`
        } else if (format === 'italic') {
          ctx.font = `italic ${fontSize}px sans-serif`
        } else if (format === 'code') {
          ctx.font = `${fontSize}px monospace`
        } else {
          ctx.font = `${fontSize}px sans-serif`
        }

        const wordWidth = ctx.measureText(word).width

        if (currentLineWidth + wordWidth > maxWidth) {
          // 绘制当前行
          ctx.fillText(currentLine, x, currentY)
          currentY += lineHeight
          currentLine = word
          currentLineWidth = wordWidth
        } else {
          currentLine += word
          currentLineWidth += wordWidth
        }
      }
    }

    // 绘制最后一行
    if (currentLine) {
      ctx.fillText(currentLine, x, currentY)
      currentY += lineHeight
    }

    return currentY
  }

  // 拆分文本为单词或字符
  splitIntoWords = (text) => {
    // 适应中英文混排
    const words = []
    let currentWord = ''

    for (let i = 0; i < text.length; i++) {
      const char = text[i]

      // 处理中文：每个中文字符单独作为一个"词"
      if (/[\u4e00-\u9fa5]/.test(char)) {
        if (currentWord) {
          words.push(currentWord)
          currentWord = ''
        }
        words.push(char)
      }
      // 处理空格
      else if (char === ' ') {
        if (currentWord) {
          words.push(currentWord)
          currentWord = ''
        }
        words.push(' ')
      }
      // 处理英文和其他字符
      else {
        currentWord += char
      }
    }

    // 添加最后一个词
    if (currentWord) {
      words.push(currentWord)
    }

    return words
  }

  // 解析带格式的文本
  parseFormattedText = (text) => {
    const segments = []
    let i = 0

    while (i < text.length) {
      // 检查粗体格式
      if (text.substr(i, 2) === '**' && text.indexOf('**', i + 2) !== -1) {
        const endPos = text.indexOf('**', i + 2)
        const boldText = text.substring(i + 2, endPos)
        segments.push({
          text: boldText,
          format: 'bold'
        })
        i = endPos + 2
      }
      // 检查斜体格式
      else if (text[i] === '*' && text.indexOf('*', i + 1) !== -1) {
        const endPos = text.indexOf('*', i + 1)
        const italicText = text.substring(i + 1, endPos)
        segments.push({
          text: italicText,
          format: 'italic'
        })
        i = endPos + 1
      }
      // 检查代码格式
      else if (text[i] === '`' && text.indexOf('`', i + 1) !== -1) {
        const endPos = text.indexOf('`', i + 1)
        const codeText = text.substring(i + 1, endPos)
        segments.push({
          text: codeText,
          format: 'code'
        })
        i = endPos + 1
      }
      // 普通文本
      else {
        // 寻找下一个格式标记
        const boldPos = text.indexOf('**', i)
        const italicPos = text.indexOf('*', i)
        const codePos = text.indexOf('`', i)

        let endPos = text.length
        if (boldPos !== -1) endPos = Math.min(endPos, boldPos)
        if (italicPos !== -1) endPos = Math.min(endPos, italicPos)
        if (codePos !== -1) endPos = Math.min(endPos, codePos)

        const normalText = text.substring(i, endPos)
        if (normalText) {
          segments.push({
            text: normalText,
            format: 'normal'
          })
        }

        i = endPos
      }
    }

    return segments
  }

  componentDidMount() {
    if (typeof wx !== 'undefined' && wx.onAppShow) {
      // 确保可以使用微信原生API
      wx.showToast({
        title: '应用已启动',
        icon: 'none',
        duration: 2000
      });
    }
  }

  render() {
    const {
      markdown,
      canvasId,
      imageUrl,
      canvasWidth,
      canvasHeight,
      isPreviewMode,
      debugInfo,
      showDebug
    } = this.state

    // 修改编辑器样式，限制其高度
    const textareaStyle = {
      height: '50vh', // 改为50%视口高度
      maxHeight: '50vh', // 限制最大高度
      padding: '10px',
      fontSize: '16px',
      lineHeight: '1.5',
      border: '1px solid #ddd',
      borderRadius: '4px',
      width: '100%',
      boxSizing: 'border-box',
      marginBottom: '80px' // 确保底部有足够空间
    }

    return (
      <View className='simple-page'>
        {/* 编辑器模式 */}
        {!isPreviewMode && (
          <View className='editor-content'>
            <Textarea
              className='simple-textarea'
              value={markdown}
              onInput={this.handleInputChange}
              placeholder='在此输入Markdown文本...

# 标题用井号开头
**粗体** 用两个星号包围
*斜体* 用单星号包围

1. 这是有序列表
2. 第二项

- 无序列表用减号
- 第二项

> 引用文本用大于号

[链接](https://example.com)'
              maxlength={-1}
              style={textareaStyle}
            />
          </View>
        )}

        {/* 预览模式 - 简化布局结构 */}
        {isPreviewMode && (
          <View className='preview-content'>
            {imageUrl ? (
              <Image src={imageUrl} mode='widthFix' />
            ) : (
              <View className='loading-text'>生成中...</View>
            )}
          </View>
        )}

        {/* 简化按钮区域 - 使用原生样式 */}
        <View className='button-area'>
          {!isPreviewMode && (
            <View
              className='action-btn generate-btn'
              onClick={this.convertToImage}
              hoverClassName='btn-hover'
            >
              生成图片
            </View>
          )}

          {isPreviewMode && (
            <View className='button-group'>
              <View
                className='action-btn back-btn'
                onClick={this.backToEditor}
              >
                返回编辑
              </View>
              <View
                className='action-btn save-btn'
                onClick={this.saveImage}
              >
                保存到相册
              </View>
            </View>
          )}
        </View>

        {/* 隐藏Canvas，确保不干扰布局 */}
        <Canvas
          type='2d'
          id={canvasId}
          className='offscreen-canvas'
          width={canvasWidth}
          height={canvasHeight}
        />

        {/* 调试面板代码保持不变... */}
      </View>
    )
  }
}
